<template>
  <div class="ku-gou-player" :class="{ active }" @mousedown.stop @dblclick.stop>
    <div
      class="play-line"
      ref="playLineDom"
      @click.stop="playerClick"
      @mouseenter="dotShow = true"
      @mouseleave="dotShow = false"
    >
      <div class="dot-line" :style="{ width: `${playDrag.width}px` }">
        <span @mousedown.stop="handleMousedown" v-if="dotShow || playDrag.start"></span>
      </div>
    </div>
    <div class="left">
      <img :src="playData.avatar" alt="avatar" />
      <div class="info">
        <div class="mb5 fs14">{{ playData.singer }} - {{ playData.name }}</div>
        <div class="icon">
          <span class="mr15"><i class="iconfont wos-heart fs14" /></span>
          <span class="mr15"><i class="iconfont wos-download fs14" /></span>
        </div>
      </div>
    </div>
    <div class="play">
      <span @click.stop="handleChangeAudio('perv')"><i class="iconfont wos-perv-play fs20" /></span>
      <span v-if="!audioLoading" class="ml40 mr40" @click.stop="handlePlayAudio">
        <i class="iconfont fs30" :class="[audioData.isPlay ? 'wos-pause' : 'wos-play']" />
      </span>
      <span v-else class="ml40 mr40" @click.stop="handlePlayAudio">
        <i class="iconfont wos-loading fs30" />
      </span>
      <span @click.stop="handleChangeAudio('next')"><i class="iconfont wos-next-play fs20" /></span>
    </div>
    <div class="right" @click.stop>
      <div class="duration">{{ $timeFormat(audioData.currentDuration) }}/{{ $timeFormat(audioData.duration) }}</div>
      <div class="voices" @mouseenter.stop="voiceShow = true" @mouseleave.stop="voiceShow = false">
        <span class="voice-player" v-if="voiceDrag.start || voiceShow">
          <em ref="voiceDom" @click.stop="voiceClick">
            <i :style="{ height: `${voiceDrag.height}px` }">
              <b class="dot" @mousedown.stop="handleVoiceMousedown" />
            </i>
            <span class="volume">
              {{ audioData.volume }}
            </span>
          </em>
        </span>
        <voice-icon class="voice-icon" :volume="audioData.volume" :muted="audioData.muted" @click.stop="handleMuted" />
      </div>
    </div>
    <audio
      :src="playData.audio"
      hidden
      ref="audioDom"
      @canplaythrough="handleCanplay"
      @pause="audioData.isPlay = false"
      @playing="audioData.isPlay = true"
      @timeupdate="handleTimeUpdate"
      @ended="emit('playEnd')"
    />
  </div>
</template>

<script setup lang="ts">
import VoiceIcon from '@/components/taskBar/voiceIcon.vue'
import { nextTick, onBeforeUnmount, reactive, ref, watch } from 'vue'
import { useSystemSettingStore } from '@/stores/desk/systemSetting'
import { useDragHook } from '@/hooks'
import type { PropType } from 'vue'
import type { IPlayer } from '@/components/systemWindow/kuGou/kuGou.vue'

const props = defineProps({
  // 选中播放器状态 播放器中文字颜色白色
  active: {
    type: Boolean as PropType<boolean>,
    default: false
  },
  // 播放数据
  playData: {
    type: Object as PropType<IPlayer>,
    required: true
  }
})

const emit = defineEmits(['timeUpdate', 'changeAudio', 'playEnd'])

const systemSettingStore = useSystemSettingStore()

// 音乐播放器DOM
const audioDom = ref<HTMLAudioElement>()
// 播放音乐数据
const audioData = reactive({ currentDuration: 0, duration: 0, isPlay: false, volume: 50, oldVolume: 50, muted: false })
// 是否显示拖动球
const dotShow = ref<boolean>(false)
// 是否显示音量
const voiceShow = ref<boolean>(false)
// 音乐加载
const audioLoading = ref<boolean>(false)

const {
  dragInfo: playDrag,
  dragDom: playLineDom,
  handleClick: playerClick,
  handleMousedown
} = useDragHook({
  default: { disX: 5 },
  click(ev: MouseEvent, proportion) {
    if (!audioDom.value) return
    audioDom.value.currentTime = proportion.proportionX * audioData.duration
  },
  move(ev: MouseEvent, proportion) {
    if (!audioDom.value) return
    audioDom.value.currentTime = proportion.proportionX * audioData.duration
  }
})

const {
  dragInfo: voiceDrag,
  dragDom: voiceDom,
  handleClick: voiceClick,
  handleMousedown: handleVoiceMousedown
} = useDragHook({
  default: { height: 66 },
  click(ev: MouseEvent, proportion) {
    if (!audioDom.value) return
    audioData.volume = Math.floor(proportion.proportionY * 100)
    audioDom.value.volume = audioData.volume * (systemSettingStore.$state.systemVolume / 100)
    audioData.oldVolume = audioData.volume
  },
  move(ev: MouseEvent, proportion) {
    if (!audioDom.value) return
    audioData.volume = Math.floor(proportion.proportionY * 100)
    audioData.oldVolume = audioData.volume
    audioDom.value.volume = proportion.proportionY * (systemSettingStore.$state.systemVolume / 100)
  }
})

// 禁音
const handleMuted = () => {
  audioData.muted = !audioData.muted
  if (audioData.muted) {
    audioData.volume = 0
    voiceDrag.height = 0
  } else {
    audioData.volume = audioData.oldVolume
    if (voiceDom.value) {
      const { height } = voiceDom.value.getBoundingClientRect()
      voiceDrag.height = (height * audioData.oldVolume) / 100
    }
  }
  if (audioDom.value) {
    audioDom.value.volume = (audioData.volume / 100) * (systemSettingStore.$state.systemVolume / 100)
  }
}
// 当音乐缓存可以播放时
const handleCanplay = () => {
  audioLoading.value = false
  audioData.duration = Math.round(audioDom.value?.duration || 0)
}
// 当音乐播放时
const handleTimeUpdate = () => {
  if (!playLineDom.value || !audioDom.value) return
  audioData.currentDuration = Math.round(audioDom.value?.currentTime || 0)
  if (!playDrag.start) {
    const { width } = playLineDom.value.getBoundingClientRect()
    playDrag.width = (audioData.currentDuration / audioData.duration) * width
  }
  emit('timeUpdate', audioDom.value?.currentTime || 0)
}
// 暂停 / 播放音乐
const handlePlayAudio = () => {
  if (!audioDom.value || audioLoading.value) return
  audioDom.value.volume = (audioData.volume / 100) * (systemSettingStore.$state.systemVolume / 100)
  audioData.isPlay ? audioDom.value?.pause() : audioDom.value?.play()
}
// 切换音乐
const handleChangeAudio = (type: string) => {
  audioDom.value?.pause()
  emit('changeAudio', type)
}

// 当播放数据变化时 停止音乐 同时切换音乐播放
watch(
  () => props.playData,
  async () => {
    if (!audioDom.value) return
    audioLoading.value = true
    if (audioData.isPlay) audioDom.value?.pause()
    await nextTick()
    audioDom.value.currentTime = 0
    audioDom.value?.play()
  }
)

// 页面销毁前 停止音乐
onBeforeUnmount(() => {
  if (audioData.isPlay) audioDom.value?.pause()
})
</script>

<style scoped lang="scss">
@keyframes loading {
  to {
    transform: rotate(1turn);
  }
}

.ku-gou-player {
  height: 70px;
  position: relative;
  z-index: 10000;
  color: var(--font-checked-color);
  display: flex;
  justify-content: space-between;

  &.active {
    color: #fff;

    ::v-deep(path) {
      stroke: #fff !important;
    }
  }

  .play-line {
    cursor: pointer;
    position: absolute;
    z-index: 10;
    width: 100%;
    height: 2px;
    background-color: var(--play-bg);

    .dot-line {
      width: 0;
      height: 2px;
      background-color: var(--play-color);
      position: absolute;
      left: 0;
      top: 0;

      > span {
        display: inline-block;
        position: absolute;
        right: -5px;
        top: 50%;
        transform: translateY(-50%);
        width: 10px;
        height: 10px;
        border-radius: 50%;
        background-color: var(--play-color);
      }
    }
  }

  .left {
    height: 100%;
    display: flex;
    align-items: center;
    padding-left: 10px;

    img {
      width: 56px;
      height: 56px;
      border-radius: 4px;
      object-fit: contain;
      margin-right: 10px;
    }

    .icon {
      display: flex;
      align-items: center;
    }
  }

  .play {
    position: absolute;
    left: 50%;
    top: 0;
    transform: translateX(-50%);
    height: 100%;
    display: flex;
    align-items: center;
    transition: color 0.3s;
    color: var(--play-color);

    span {
      cursor: pointer;
    }

    .wos-loading {
      display: inline-block;
      transform-origin: center center;
      animation: loading 0.6s infinite linear;
    }
  }

  .right {
    padding-right: 40px;
    height: 100%;
    display: flex;
    align-items: center;

    .duration {
      height: 16px;
    }

    .voices {
      width: 16px;
      height: 16px;
      display: flex;
      align-items: center;
      margin-left: 10px;
      position: relative;
      z-index: 10;

      .voice-player {
        position: absolute;
        z-index: 10;
        top: -15px;
        left: 50%;
        transform: translateX(-50%) translateY(-100%);
        width: 60px;
        height: 200px;
        border-radius: 4px;
        background-color: var(--voice-wrapper-bg);
        box-shadow: var(--voice-shadow);

        &::after {
          content: '';
          position: absolute;
          left: 50%;
          bottom: -20px;
          transform: translateX(-50%);
          border: 10px solid transparent;
          border-top-color: var(--voice-wrapper-bg);
        }

        > em {
          position: absolute;
          top: 26px;
          left: 50%;
          transform: translateX(-50%);
          width: 6px;
          height: 132px;
          border-radius: 3px;
          display: inline-block;
          background-color: var(--voice-bg);

          i {
            cursor: pointer;

            display: inline-block;
            position: absolute;
            left: 0;
            bottom: 0;
            width: 6px;
            height: 50%;
            border-radius: 3px;
            background-color: var(--play-color);

            .dot {
              display: inline-block;
              position: absolute;
              left: 50%;
              top: -5px;
              transform: translateX(-50%);
              width: 10px;
              height: 10px;
              border-radius: 50%;
              background-color: var(--play-color);
            }
          }
        }

        .volume {
          color: var(--font-checked-color);
          position: absolute;
          bottom: -26px;
          left: 50%;
          transform: translateX(-50%);
        }
      }

      .voice-icon {
        width: 16px;
        height: 16px;

        ::v-deep(path) {
          stroke: var(--font-checked-color);
        }
      }
    }
  }
}
</style>
